package com.xbongbong.saas.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.constant.SizeConstant;
import com.xbongbong.paas.constant.TimeConstant;
import com.xbongbong.paas.domain.entity.PaasFormDataEntity;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.ext.ConditionsEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasFormEntityExt;
import com.xbongbong.paas.elasticsearch.model.PaasEsModel;
import com.xbongbong.paas.elasticsearch.pojo.XbbAggregatedPage;
import com.xbongbong.paas.elasticsearch.util.EsHelper;
import com.xbongbong.paas.elasticsearch.util.EsUtil;
import com.xbongbong.paas.elasticsearch.util.XbbElasticsearchRestTemplate;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.FlowStatusEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.enums.PlatFormEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.field.ItemPoJo;
import com.xbongbong.paas.field.UnitItemPoJo;
import com.xbongbong.paas.help.subform.TransferSubFormHelper;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.pojo.ProductFieldPojo;
import com.xbongbong.paas.pojo.dto.FormDataListDTO;
import com.xbongbong.paas.pojo.vo.PaasFormDataEsListVO;
import com.xbongbong.paas.redis.RedisPrefixConstant;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.helper.PageHelper;
import com.xbongbong.paas.toolbox.util.Arith;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CloneUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.PageHelperUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.pro.businessdata.pojo.dto.BusinessDataDTO;
import com.xbongbong.pro.businessproduct.pojo.dto.BusinessProductBatchListDTO;
import com.xbongbong.pro.businessproduct.pojo.dto.BussinessProductBatchAutoMatchDTO;
import com.xbongbong.pro.businessproduct.pojo.vo.BusinessProductBatchListVO;
import com.xbongbong.pro.constant.BusinessConstant;
import com.xbongbong.pro.constant.ElasticConstant;
import com.xbongbong.pro.detailtab.pojo.BatchAutoMatchProductPoJo;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.BusinessTypeErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.ProductErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.product.pojo.vo.ProductBatchGetVO;
import com.xbongbong.pro.productstockinfo.pojo.dto.ProductStockInfoDeleteBatchDTO;
import com.xbongbong.pro.productstockinfo.pojo.vo.ProductStockInfoDeleteBatchVO;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.constant.StockConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.InstockProductEntity;
import com.xbongbong.saas.domain.entity.OutstockProductEntity;
import com.xbongbong.saas.domain.entity.ProductStockEntity;
import com.xbongbong.saas.domain.entity.ProductStockInfoEntity;
import com.xbongbong.saas.domain.entity.ProductWarehouseEntity;
import com.xbongbong.saas.domain.entity.ext.InstockEntityExt;
import com.xbongbong.saas.domain.entity.ext.OutstockEntityExt;
import com.xbongbong.saas.domain.entity.ext.ProductEntityExt;
import com.xbongbong.saas.enums.ListGroupEnum;
import com.xbongbong.saas.enums.ListOptionEnum;
import com.xbongbong.saas.enums.SelectProductEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.AssembleEnum;
import com.xbongbong.saas.enums.business.ProductEnum;
import com.xbongbong.saas.enums.business.SelectBatchEnum;
import com.xbongbong.saas.enums.product.InventoryProductEnum;
import com.xbongbong.saas.enums.subform.ProductStockSubFormEnum;
import com.xbongbong.saas.enums.subform.ProductWarehouseSubFormEnum;
import com.xbongbong.saas.help.SaasFormHelp;
import com.xbongbong.saas.model.IndexTypeModel;
import com.xbongbong.saas.model.InstockModel;
import com.xbongbong.saas.model.InstockProductModel;
import com.xbongbong.saas.model.OutstockModel;
import com.xbongbong.saas.model.OutstockProductModel;
import com.xbongbong.saas.model.ProductModel;
import com.xbongbong.saas.model.ProductStockInfoModel;
import com.xbongbong.saas.model.ProductStockModel;
import com.xbongbong.saas.service.ProductStockInfoService;
import com.xbongbong.saas.service.WarehouseService;
import com.xbongbong.saas.service.toolbox.help.AttrDecimalPrecisionHelper;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.join.query.HasParentQueryBuilder;
import org.elasticsearch.join.query.JoinQueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import static com.xbongbong.paas.elasticsearch.constant.EsNormalConstant.MINI_MUM_SHOULD_MATCH;
import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.matchPhraseQuery;
import static org.elasticsearch.index.query.QueryBuilders.rangeQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.elasticsearch.index.query.QueryBuilders.termsQuery;

/**
 * 产品库存信息接口实现类
 *
 * @author chaoxiong.lei
 * @date 2019/2/26 20:51
 */
@Service("productStockInfoService")
public class ProductStockInfoServiceImpl implements ProductStockInfoService {

    private static final Logger LOG = LoggerFactory.getLogger(ProductStockInfoServiceImpl.class);

    @Resource
    private ProductStockInfoModel productStockInfoModel;
    @Resource
    private InstockModel instockModel;
    @Resource
    private OutstockModel outstockModel;
    @Resource
    private InstockProductModel instockProductModel;
    @Resource
    private OutstockProductModel outstockProductModel;
    @Resource
    private ProductModel productModel;
    @Resource
    private EsHelper esHelper;
    @Resource
    private XbbElasticsearchRestTemplate xbbElasticsearchRestTemplate;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private AttrDecimalPrecisionHelper attrDecimalPrecisionHelper;
    @Resource
    private SaasFormHelp saasFormHelp;
    @Resource
    private WarehouseService warehouseService;
    @Resource
    private ProductStockModel productStockModel;
    @Resource
    private TransferSubFormHelper transferSubFormHelper;
    @Resource
    private PaasEsModel paasEsModel;
    @Resource
    private IndexTypeModel indexTypeModel;

    @Override
    public ProductStockInfoDeleteBatchVO deleteBatch(ProductStockInfoDeleteBatchDTO productStockInfoDeleteBatchDTO) throws XbbException {
        ProductStockInfoDeleteBatchVO productStockInfoDeleteBatchVO = new ProductStockInfoDeleteBatchVO();
        try {
            String corpid = productStockInfoDeleteBatchDTO.getCorpid();
            List<Long> refIdIn = productStockInfoDeleteBatchDTO.getRefIdIn();
            Integer refType = productStockInfoDeleteBatchDTO.getRefType();
            productStockInfoModel.deleteByRefIdIn(corpid, refIdIn, refType);
        } catch (Exception e) {
            LOG.error("ProductStockInfoServiceImpl.deleleBatch 批量删除出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return productStockInfoDeleteBatchVO;
    }

    /**
     * 获取库存产品信息时要获取审批通过的数据
     *
     * @param corpid     公司id
     * @param extraParam 条件
     * @return 实体
     */
    @Override
    public List<ProductStockInfoEntity> getValidBatchInfoList(String corpid, Map<String, Object> extraParam) {
        //TODO haibin.zhang 为什么走库
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(ParameterConstant.CORPID, corpid);
        param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        param.put("flowStatusIn", Arrays.asList(FlowStatusEnum.NOT_NEED_APPROVAL.getType(), FlowStatusEnum.PASS.getType()));
        List<InstockEntityExt> instockList = instockModel.findEntitys(param);
        List<OutstockEntityExt> outstockList = outstockModel.findEntitys(param);

        List<Long> instockIdIn = new ArrayList<>();
        instockIdIn.add(-1L);
        for (InstockEntityExt instockEntity : instockList) {
            instockIdIn.add(instockEntity.getId());
        }
        List<Long> outstockIdIn = new ArrayList<>();
        outstockIdIn.add(-1L);
        for (OutstockEntityExt outstockEntity : outstockList) {
            outstockIdIn.add(outstockEntity.getId());
        }
        param.clear();
        param.put(ParameterConstant.CORPID, corpid);
        param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        param.put("instockIdIn", instockIdIn);
        List<InstockProductEntity> instockProductList = instockProductModel.findEntitys(param);
        param.remove("instockIdIn");
        param.put("outstockIdIn", outstockIdIn);
        List<OutstockProductEntity> outstockProductList = outstockProductModel.findEntitys(param);

        List<Long> instockProductIdIn = new ArrayList<>();
        instockProductIdIn.add(-1L);
        for (InstockProductEntity instockProductEntity : instockProductList) {
            instockProductIdIn.add(instockProductEntity.getId());
        }

        List<Long> outstockProductIdIn = new ArrayList<>();
        outstockProductIdIn.add(-1L);
        for (OutstockProductEntity outstockProductEntity : outstockProductList) {
            outstockProductIdIn.add(outstockProductEntity.getId());
        }

        extraParam.put("refType", XbbRefTypeEnum.INSTOCK_PRODUCT.getCode());
        extraParam.put("refIdIn", instockProductIdIn);
        List<ProductStockInfoEntity> instockProductStockInfoList = productStockInfoModel.findEntitys(extraParam);

        extraParam.put("refType", XbbRefTypeEnum.OUTSTOCK_PRODUCT.getCode());
        extraParam.put("refIdIn", outstockProductIdIn);
        List<ProductStockInfoEntity> outstockProductStockInfoList = productStockInfoModel.findEntitys(extraParam);

        List<ProductStockInfoEntity> productStockInfoList = new ArrayList<>();
        productStockInfoList.addAll(instockProductStockInfoList);
        productStockInfoList.addAll(outstockProductStockInfoList);
        return productStockInfoList;
    }

    /**
     * 获取产品批次
     *
     * @param businessProductBatchListDTO
     * @return 产品批次列表
     * @author 周智
     * 创建时间：2018-1-3 13:56
     */
    @Override
    public List<ProductBatchGetVO> getProductBatchList(BusinessProductBatchListDTO businessProductBatchListDTO) throws XbbException {
        String corpid = businessProductBatchListDTO.getCorpid();
        // 产品id
        Long productId = businessProductBatchListDTO.getProductId();
        ProductEntityExt product = productModel.getByKey(productId, corpid);

        if (product == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100018);
        }
        JSONObject dataList = product.getData();
        if (Objects.equals(dataList.getLong(ProductEnum.PARENT_ID.getAttr()), 0L)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100018);
        }
        // 仓库id
        Long warehouseId = businessProductBatchListDTO.getWarehouseId();
        if (warehouseId == null) {
            return new ArrayList<>();
        }
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        boolQueryBuilder.filter(termQuery("corpid.keyword",corpid));
        boolQueryBuilder.filter(termQuery(StringConstant.DEL,DelEnum.NORMAL.getDel()));
        boolQueryBuilder.filter(termQuery(ProductStockSubFormEnum.getEsAttr(ProductStockSubFormEnum.PRODUCT_ID), productId));
        boolQueryBuilder.filter(termQuery(ProductStockSubFormEnum.getEsAttr(ProductStockSubFormEnum.WAREHOUSE_ID), warehouseId));
        boolQueryBuilder.filter(rangeQuery(ProductStockSubFormEnum.getEsAttr(ProductStockSubFormEnum.NUM)).gt(0));
        boolQueryBuilder.filter(termQuery(ProductStockSubFormEnum.getEsAttr(ProductStockSubFormEnum.WAREHOUSE_CHECKED), 1));
        List<PaasFormDataEntity> productStockEntityList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_PRODUCT_STOCK_INFO,boolQueryBuilder,PaasFormDataEntity.class,null);
        List<ProductStockEntity> productStockEntities = transferSubFormHelper.transferFormDataToProductStockList(productStockEntityList);
        List<ProductBatchGetVO> productSavePojoList = new ArrayList<>();
        for (ProductStockEntity entity : productStockEntities){
            if (StringUtil.isEmpty(entity.getBatch())){
                continue;
            }
            ProductBatchGetVO productBatchGetVO = new ProductBatchGetVO();
            BeanUtil.copyProperties(entity, productBatchGetVO);
            productBatchGetVO.setProductNum(entity.getNum());
            ProductFieldPojo costField = saasFormHelp.getProductFieldPojo(RedisPrefixConstant.PRODUCT_COST,ProductEnum.COST.getAttr(), corpid);
            Integer accuracy = costField.getAccuracy();
            productBatchGetVO.setProductCost(attrDecimalPrecisionHelper.setPrecision(entity.getCost(),accuracy));
            Long guaranteePeriod = entity.getGuaranteePeriod();
            if (Objects.nonNull(guaranteePeriod)) {
                guaranteePeriod = guaranteePeriod / TimeConstant.SECONDS_PER_DAY;
                productBatchGetVO.setGuaranteePeriod(guaranteePeriod);
            }
            Long produceDate = entity.getProduceDate();
//            if (Objects.nonNull(produceDate)) {
//                productBatchGetVO.setProduceDate(DateTimeUtil.getStringEpochSecond(produceDate, DateTimeUtil.SDFDate));
//            }
            productBatchGetVO.setProduceDate(produceDate);
            productBatchGetVO.setCost(entity.getCost());
            productSavePojoList.add(productBatchGetVO);
        }
        return productSavePojoList;
    }

    @Override
    public BusinessProductBatchListVO getNewProductBatchList(BusinessProductBatchListDTO businessProductBatchListDTO) throws XbbException {
        BusinessProductBatchListVO businessProductBatchListVO = new BusinessProductBatchListVO();
        Integer businessType = businessProductBatchListDTO.getBusinessType();
        boolean isOutStock = StockConstant.OUTSTOCK_TYPE_LIST.contains(businessType) || Objects.equals(businessType, XbbRefTypeEnum.TRANSFER.getCode()) || Objects.equals(businessType, XbbRefTypeEnum.INVENTORY.getCode())
                || (Objects.equals(businessType, XbbRefTypeEnum.ASSEMBLE.getCode()) && Objects.equals(businessProductBatchListDTO.getAttr(), AssembleEnum.OUT_PRODUCTS.getAttr()));
        String corpid = businessProductBatchListDTO.getCorpid();
        // 产品id
        Long productId = businessProductBatchListDTO.getProductId();
        List<UnitItemPoJo> unitRate = businessProductBatchListDTO.getUnitRate();
        boolean enableMultiUnit = !CollectionUtils.isEmpty(unitRate);
        ProductEntityExt product = productModel.getByKey(productId, corpid);
        if (product == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100018);
        }
        JSONObject dataList = product.getData();
        if (Objects.equals(dataList.getLong(ProductEnum.PARENT_ID.getAttr()), 0L)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100018);
        }
        // 仓库id
        Long warehouseId = businessProductBatchListDTO.getWarehouseId();
        List<FieldAttrEntity> headList = new ArrayList<>();
        FieldAttrEntity fieldAttrEntity;
        boolean noShelf = StringUtil.isEmpty(dataList.getString(ProductEnum.SHELF_LIFE_DAYS.getAttr()));
        for (SelectBatchEnum selectBatchEnum : SelectBatchEnum.values()) {
            if (noShelf && SelectBatchEnum.noShelfEnumList.contains(selectBatchEnum)) {
                continue;
            }
            if (!isOutStock && SelectBatchEnum.THIS_OUT_STOCK.equals(selectBatchEnum)) {
                continue;
            }
            if (SelectBatchEnum.BASE_UNIT.equals(selectBatchEnum) && !enableMultiUnit) {
                continue;
            }
            fieldAttrEntity = new FieldAttrEntity();
            BeanUtil.copyProperties(selectBatchEnum, fieldAttrEntity);
            fieldAttrEntity.setAttrName(I18nMessageUtil.getMessage(selectBatchEnum.getAttrName()));
            if (SelectBatchEnum.THIS_OUT_STOCK.equals(selectBatchEnum) && Objects.equals(businessType, XbbRefTypeEnum.INVENTORY.getCode())) {
                fieldAttrEntity.setAttrName(InventoryProductEnum.NUM.getAttrName());
            }
            headList.add(fieldAttrEntity);
        }
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(ParameterConstant.CORPID, corpid);
        param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        param.put(ParameterConstant.PRODUCT_ID, productId);
        param.put(ParameterConstant.WAREHOUSE_ID, warehouseId);
        param.put("numNotZero", 1);
        param.put("wareHouseChecked", 1);
        if (StringUtil.isNotEmpty(businessProductBatchListDTO.getBatch())) {
            param.put("batchLike", businessProductBatchListDTO.getBatch());
        }
        if (noShelf) {
            param.put(ParameterConstant.ORDER_BY_STR, "add_time asc, id asc");
        } else {
            param.put(ParameterConstant.ORDER_BY_STR, "expire_date asc, id asc");
        }
        param.put(ParameterConstant.PAGE, businessProductBatchListDTO.getPage());
        PageHelper pageHelper = PageHelperUtil.getPageHelper(param, productStockModel, businessProductBatchListDTO.getPageSize());
        List<ProductStockEntity> productStockEntityList = (List<ProductStockEntity>) PageHelperUtil.getEntityList(param, pageHelper, productStockModel);
       /* BoolQueryBuilder boolQueryBuilder = boolQuery();
        boolQueryBuilder.filter(termQuery("corpid.keyword",corpid));
        boolQueryBuilder.filter(termQuery(StringConstant.DEL,DelEnum.NORMAL.getDel()));
        boolQueryBuilder.filter(termQuery("productId",productId));
        boolQueryBuilder.filter(termQuery("warehouseId",warehouseId));
        boolQueryBuilder.filter(rangeQuery("num").gt(0));
        boolQueryBuilder.filter(termQuery("warehouseChecked", 1));
        if (StringUtil.isNotEmpty(businessProductBatchListDTO.getBatch())) {
            boolQueryBuilder.filter(matchQuery("batch", businessProductBatchListDTO.getBatch()));
        }
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(boolQueryBuilder);
        if (noShelf) {
            sourceBuilder.sort(new FieldSortBuilder(StringConstant.ADD_TIME).order(SortOrder.ASC));
        } else {
            sourceBuilder.sort(new FieldSortBuilder(SelectBatchEnum.EXPIRE_DATE.getAttr()).order(SortOrder.ASC));
        }
        //分页
        PageRequest pageRequest = EsUtil.setPage(sourceBuilder, businessProductBatchListDTO.getPage(), businessProductBatchListDTO.getPageSize());
        SearchRequest searchRequest = new SearchRequest(IndexTypeEnum.IDX_SAAS_PRODUCT_STOCK_INFO.getIndex()).types(IndexTypeEnum.IDX_SAAS_PRODUCT_STOCK_INFO.getType());
        searchRequest.source(sourceBuilder);
        AggregatedPage<ProductStockEntity> esEntities = xbbElasticsearchRestTemplate.queryForPage(pageRequest,searchRequest, ProductStockEntity.class);
        if (esEntities == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        List<ProductStockEntity> productStockEntityList = new ArrayList<>(esEntities.getContent());
        long totalNum = esEntities.getTotalElements();
        PageHelper pageHelper = new PageHelper(businessProductBatchListDTO.getPage(), businessProductBatchListDTO.getPageSize());
        pageHelper.setRowsCount((int) totalNum);*/
        List<ProductBatchGetVO> productSavePojoList = new ArrayList<>();
        ItemPoJo unitItem = new ItemPoJo();
        if (enableMultiUnit) {
            for (UnitItemPoJo unitItemPoJo : unitRate) {
                if (Objects.equals(unitItemPoJo.getIsBase(), 1)) {
                    unitItem.setIsOther(null);
                    unitItem.setText(unitItemPoJo.getText());
                    unitItem.setValue(unitItemPoJo.getValue());
                    break;
                }
            }
        }
        for (ProductStockEntity entity : productStockEntityList){
            if (StringUtil.isEmpty(entity.getBatch())){
                continue;
            }
            ProductBatchGetVO productBatchGetVO = new ProductBatchGetVO();
            productBatchGetVO.setId(entity.getId());
            productBatchGetVO.setParentId(entity.getParentId());
            productBatchGetVO.setNum(entity.getNum());
            productBatchGetVO.setBatch(entity.getBatch());
            productBatchGetVO.setProductNum(entity.getNum());
            ProductFieldPojo costField = saasFormHelp.getProductFieldPojo(RedisPrefixConstant.PRODUCT_COST,ProductEnum.COST.getAttr(), corpid);
            Integer accuracy = costField.getAccuracy();
            productBatchGetVO.setProductCost(attrDecimalPrecisionHelper.setPrecision(entity.getCost(),accuracy));
            Long produceDate = entity.getProduceDate();
            Long guaranteePeriod = entity.getGuaranteePeriod();
            if (Objects.nonNull(guaranteePeriod) && !Objects.equals(produceDate, 0L)) {
                productBatchGetVO.setProduceDate(produceDate);
                guaranteePeriod = guaranteePeriod / TimeConstant.SECONDS_PER_DAY;
                productBatchGetVO.setGuaranteePeriod(guaranteePeriod);
                productBatchGetVO.setExpireDate(produceDate + guaranteePeriod * TimeConstant.SECONDS_PER_DAY);
            }
            productBatchGetVO.setCost(entity.getCost());
            productBatchGetVO.setStock(entity.getNum());
            if (enableMultiUnit) {
                productBatchGetVO.setUnit(unitItem);
                productBatchGetVO.setBaseUnit(unitItem.getText());
            }
            productSavePojoList.add(productBatchGetVO);
        }
        businessProductBatchListVO.setPageHelper(pageHelper);
        businessProductBatchListVO.setHeadList(headList);
        businessProductBatchListVO.setBatchList(productSavePojoList);
        return businessProductBatchListVO;
    }

    @Override
    public PaasFormDataEsListVO getProductWarehouse(BusinessDataDTO businessDataDTO) throws XbbException {
        String corpid = businessDataDTO.getCorpid();
        Long productId = businessDataDTO.getParentId();
        Integer businessType = businessDataDTO.getBusinessType();

        ProductEntityExt product = productModel.getByKey(productId, corpid);
        if (product == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100404);
        }
        List<Long> warehouseIdList = warehouseService.getWarehouseIdsByPermission(businessDataDTO.getLoginUser(),businessDataDTO.getLoginUser().getDepSet());
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        boolQueryBuilder.filter(termQuery("corpid.keyword",corpid));
        boolQueryBuilder.filter(termQuery(StringConstant.DEL,DelEnum.NORMAL.getDel()));
        boolQueryBuilder.filter(termQuery(ProductWarehouseSubFormEnum.getEsAttr(ProductWarehouseSubFormEnum.PRODUCT_ID),productId));
        // 仓库库存表有全仓数据，不要查出来
        boolQueryBuilder.filter(termsQuery(ProductWarehouseSubFormEnum.getEsAttr(ProductWarehouseSubFormEnum.WAREHOUSE_ID),warehouseIdList));
        boolQueryBuilder.mustNot(termQuery(ProductWarehouseSubFormEnum.getEsAttr(ProductWarehouseSubFormEnum.WAREHOUSE_ID), 0L));
        boolQueryBuilder.filter(termQuery(ProductWarehouseSubFormEnum.getEsAttr(ProductWarehouseSubFormEnum.WAREHOUSE_CHECKED),1));
        if (StringUtil.isNotEmpty(businessDataDTO.getNameLike())){
            boolQueryBuilder.filter(matchPhraseQuery(ProductWarehouseSubFormEnum.getAttrConnectData(ProductWarehouseSubFormEnum.WAREHOUSE_NAME),businessDataDTO.getNameLike()));
        }
        boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, IndexTypeEnum.IDX_SAAS_PRODUCT_WAREHOUSE.getType()));
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(boolQueryBuilder);
        SearchRequest searchRequest = new SearchRequest(IndexTypeEnum.IDX_SAAS_PRODUCT_WAREHOUSE.getIndex());
        searchRequest.source(sourceBuilder);
        //分页
        Integer page = businessDataDTO.getPage();
        Integer pageSize = businessDataDTO.getPageSize();
        PageRequest  pageRequest= EsUtil.setPage(sourceBuilder, page, pageSize);
        XbbAggregatedPage<PaasFormDataEntity> esEntities = xbbElasticsearchRestTemplate.queryForPages(pageRequest,searchRequest,PaasFormDataEntity.class);
        List<PaasFormDataEntity> list = esEntities.getContent();
        List<ProductWarehouseEntity> productWarehouseEntities = transferSubFormHelper.transferFormDataToProductWarehouseList(list);
        List<PaasFormDataEntityExt> paasFormDataEntityExtList = new ArrayList<>();
        for (ProductWarehouseEntity entity : productWarehouseEntities){
            PaasFormDataEntityExt entityExt = new PaasFormDataEntityExt();
            JSONObject data = new JSONObject();
            data.put(ProductEnum.STOCK.getAttr(),entity.getNum());
            data.put(ProductEnum.COST.getAttr(),entity.getCost());
            data.put(ProductEnum.WAREHOUSE.getAttr(),entity.getWarehouseName());
            entityExt.setData(data);
            JSONObject sourceData = new JSONObject();
            sourceData.put(ProductEnum.STOCK.getAttr(),entity.getNum());
            sourceData.put(ProductEnum.COST.getAttr(),entity.getCost());
            entityExt.setSourceData(sourceData);
            entityExt.setId(entity.getWarehouseId());
            entityExt.setDataId(entity.getWarehouseId());
            paasFormDataEntityExtList.add(entityExt);
        }
        PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByBusinessType(XbbRefTypeEnum.PRODUCT.getCode(),corpid);
        List<FieldAttrEntity> explainList = JSONArray.parseArray(paasFormExplainEntity.getExplains(),FieldAttrEntity.class);
        List<FieldAttrEntity>  fieldAttrEntityList= new ArrayList<>();
        for (FieldAttrEntity fieldAttrEntity : explainList) {
            if (fieldAttrEntity.getAttr().equals(ProductEnum.STOCK.getAttr())){
                fieldAttrEntityList.add(fieldAttrEntity);
            }else if (Objects.equals(fieldAttrEntity.getAttr(),ProductEnum.WAREHOUSE.getAttr())){
                fieldAttrEntity.setFieldType(FieldTypeEnum.TEXT.getType());
                fieldAttrEntityList.add(0,fieldAttrEntity);
            }
        }
        PaasFormEntityExt paasFormEntityExt = new PaasFormEntityExt();
        paasFormEntityExt.setBusinessName(XbbRefTypeEnum.getByCode(businessType).getName());
        paasFormEntityExt.setMainAttr(ProductEnum.WAREHOUSE.getAttr());

        PageHelper pageHelper = new PageHelper(page, pageSize);
        pageHelper.setRowsCount((int)esEntities.getTotalElements());
        PaasFormDataEsListVO paasFormDataEsListVO = new PaasFormDataEsListVO();
        paasFormDataEsListVO.setPageHelper(pageHelper);
        paasFormDataEsListVO.setHeadList(fieldAttrEntityList);
        paasFormDataEsListVO.setPaasFormDataESList(paasFormDataEntityExtList);
        paasFormDataEsListVO.setForm(paasFormEntityExt);
        return paasFormDataEsListVO;
    }

    @Override
    public BusinessProductBatchListVO getProductAutoMatchBatch(BussinessProductBatchAutoMatchDTO bussinessProductBatchAutoMatchDTO) throws XbbException{
        BusinessProductBatchListVO businessProductBatchListVO = new BusinessProductBatchListVO();
        Integer businessType = bussinessProductBatchAutoMatchDTO.getBusinessType();
        boolean isOutStock = StockConstant.OUTSTOCK_TYPE_LIST.contains(businessType)
                || Objects.equals(businessType, XbbRefTypeEnum.TRANSFER.getCode())
                || Objects.equals(businessType, XbbRefTypeEnum.INVENTORY.getCode())
                || (Objects.equals(businessType, XbbRefTypeEnum.ASSEMBLE.getCode()) && Objects.equals(bussinessProductBatchAutoMatchDTO.getAttr(), AssembleEnum.OUT_PRODUCTS.getAttr()));
        if (!isOutStock) {
            throw new XbbException(BusinessTypeErrorCodeEnum.API_ERROR_361001);
        }
        String corpid = bussinessProductBatchAutoMatchDTO.getCorpid();
        // 产品id
        List<BatchAutoMatchProductPoJo> productPoJos = bussinessProductBatchAutoMatchDTO.getProductList();
        List<Long> productIds = new ArrayList<>();
        List<String> subIds = new ArrayList<>();
        Map<String, BatchAutoMatchProductPoJo> productMap = new HashMap<>(productPoJos.size());
        for (BatchAutoMatchProductPoJo product : productPoJos) {
            String productSubId;
            if (Objects.equals(bussinessProductBatchAutoMatchDTO.getPlatform(), PlatFormEnum.WEB.getValue())) {
                productSubId = product.getSubId();
            }else{
                productSubId = product.getGuid();
            }
            subIds.add(productSubId);
            productIds.add(product.getId());
            if (Objects.isNull(product.getNum())) {
                throw new XbbException(ProductErrorCodeEnum.API_ERROR_205069);
            }
            //多单位的数量先做一层转换
            if (Objects.equals(product.getEnableMultiUnit(), 1)) {
                Long unitValue = Long.valueOf(product.getUnit().getValue().toString());
                List<UnitItemPoJo> unitRate = product.getUnitRate();
                for (UnitItemPoJo unitItemPoJo : unitRate) {
                    if (Objects.equals(unitItemPoJo.getValue(), unitValue)) {
                        product.setNum(Arith.mul(product.getNum(), unitItemPoJo.getRate()));
                    }
                    if (Objects.equals(unitItemPoJo.getIsBase(), 1)) {
                        ItemPoJo itemPoJo = new ItemPoJo();
                        itemPoJo.setIsOther(null);
                        itemPoJo.setText(unitItemPoJo.getText());
                        itemPoJo.setValue(unitItemPoJo.getValue());
                        product.setUnit(itemPoJo);
                    }
                }
            }
            productMap.put(productSubId, product);
        }
        List<ProductEntityExt> productList = productModel.getProductListByIdIn(corpid, productIds, DelEnum.NORMAL.getDel());
        if (productList.isEmpty()) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100018);
        }
        HashSet<Long> shelfSet = new HashSet<>();
        HashSet<Long> noShelfSet = new HashSet<>();
        for (ProductEntityExt productEntityExt : productList) {
            JSONObject data = productEntityExt.getData();
            if (StringUtil.isEmpty(data.getString(ProductEnum.SHELF_LIFE_DAYS.getAttr()))) {
                noShelfSet.add(productEntityExt.getId());
            }else {
                shelfSet.add(productEntityExt.getId());
            }
        }
        Map<String, List<ProductStockEntity>> stockMap = new HashMap<>();

        //未开启保质期则按照批次创建日期升序匹配
        if (!noShelfSet.isEmpty()) {
            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
            BoolQueryBuilder boolQueryBuilder = boolQuery();
            boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
            boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
            boolQueryBuilder.filter(termQuery(ProductStockSubFormEnum.getEsAttr(ProductStockSubFormEnum.WAREHOUSE_CHECKED), 1));
            boolQueryBuilder.filter(termsQuery(ProductStockSubFormEnum.getEsAttr(ProductStockSubFormEnum.PRODUCT_ID), noShelfSet));
            boolQueryBuilder.filter(rangeQuery(ProductStockSubFormEnum.getEsAttr(ProductStockSubFormEnum.NUM)).gt(0));
            for (Map.Entry<String, BatchAutoMatchProductPoJo> matchProductPoJoEntry : productMap.entrySet()) {
                BatchAutoMatchProductPoJo value = matchProductPoJoEntry.getValue();
                BoolQueryBuilder shouldBuilder = boolQuery();
                shouldBuilder.filter(termQuery(ProductStockSubFormEnum.getEsAttr(ProductStockSubFormEnum.PRODUCT_ID), value.getId()));
                shouldBuilder.filter(termQuery(ProductStockSubFormEnum.getEsAttr(ProductStockSubFormEnum.WAREHOUSE_ID), value.getWarehouseId()));
                boolQueryBuilder.should(shouldBuilder);
            }
            boolQueryBuilder.minimumShouldMatch(MINI_MUM_SHOULD_MATCH);
            boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, IndexTypeEnum.IDX_SAAS_PRODUCT_STOCK_INFO.getType()));
            sourceBuilder.sort(new FieldSortBuilder(FieldTypeEnum.ADDTIME.getAlias()).order(SortOrder.ASC)).sort(new FieldSortBuilder(StringConstant.SAAS_LINK_BUSINESS_ID).order(SortOrder.ASC));
            Integer pageSize = SizeConstant.PAGE_SIZE;
            PageRequest pageRequest = EsUtil.setPage(sourceBuilder, 1, pageSize);
            sourceBuilder.query(boolQueryBuilder);
            SearchRequest searchRequest = new SearchRequest(IndexTypeEnum.IDX_SAAS_PRODUCT_STOCK_INFO.getIndex());
            searchRequest.source(sourceBuilder);
            XbbAggregatedPage<PaasFormDataEntity> esEntities = xbbElasticsearchRestTemplate.queryForPages(pageRequest, searchRequest, PaasFormDataEntity.class);
            if (esEntities != null) {
                List<ProductStockEntity> productStockEntities = transferSubFormHelper.transferFormDataToProductStockList(esEntities.getContent());
                for (ProductStockEntity stockEntity : productStockEntities) {
                    String key = stockEntity.getProductId() + "_" +stockEntity.getWarehouseId();
                    stockEntity.setTransferNum(stockEntity.getNum());
                    List<ProductStockEntity> stockEntityList = stockMap.getOrDefault(key, new ArrayList<>());
                    stockEntityList.add(stockEntity);
                    stockMap.put(key, stockEntityList);
                }
            }
        }

        if (!shelfSet.isEmpty()) {
            //开启保质期则按照到期日期升序匹配
            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
            BoolQueryBuilder boolQueryBuilder = boolQuery();
            boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
            boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
            boolQueryBuilder.filter(termQuery(ProductStockSubFormEnum.getEsAttr(ProductStockSubFormEnum.WAREHOUSE_CHECKED), 1));
            boolQueryBuilder.filter(termsQuery(ProductStockSubFormEnum.getEsAttr(ProductStockSubFormEnum.PRODUCT_ID), shelfSet));
            boolQueryBuilder.filter(rangeQuery(ProductStockSubFormEnum.getEsAttr(ProductStockSubFormEnum.NUM)).gt(0));
            for (Map.Entry<String, BatchAutoMatchProductPoJo> poJoEntry : productMap.entrySet()) {
                BatchAutoMatchProductPoJo value = poJoEntry.getValue();
                BoolQueryBuilder shouldBuilder = boolQuery();
                shouldBuilder.filter(termQuery(ProductStockSubFormEnum.getEsAttr(ProductStockSubFormEnum.PRODUCT_ID), value.getId()));
                shouldBuilder.filter(termQuery(ProductStockSubFormEnum.getEsAttr(ProductStockSubFormEnum.WAREHOUSE_ID), value.getWarehouseId()));
                boolQueryBuilder.should(shouldBuilder);
            }
            boolQueryBuilder.minimumShouldMatch(MINI_MUM_SHOULD_MATCH);
            boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, IndexTypeEnum.IDX_SAAS_PRODUCT_STOCK_INFO.getType()));
            sourceBuilder.sort(new FieldSortBuilder(ProductStockSubFormEnum.getEsAttr(ProductStockSubFormEnum.EXPIRE_DATE)).order(SortOrder.ASC)).sort(new FieldSortBuilder(StringConstant.SAAS_LINK_BUSINESS_ID).order(SortOrder.ASC));
            Integer page = 1;
            Integer pageSize = SizeConstant.PAGE_SIZE;
            PageRequest pageRequest = EsUtil.setPage(sourceBuilder, page, pageSize);
            sourceBuilder.query(boolQueryBuilder);
            SearchRequest searchRequest = new SearchRequest(IndexTypeEnum.IDX_SAAS_PRODUCT_STOCK_INFO.getIndex());
            searchRequest.source(sourceBuilder);
            XbbAggregatedPage<PaasFormDataEntity> esEntities = xbbElasticsearchRestTemplate.queryForPages(pageRequest, searchRequest, PaasFormDataEntity.class);
            if (esEntities != null) {
                List<ProductStockEntity> productStockEntities = transferSubFormHelper.transferFormDataToProductStockList(esEntities.getContent());
                for (ProductStockEntity stockEntity : productStockEntities) {
                    String key = stockEntity.getProductId() + "_" +stockEntity.getWarehouseId();
                    List<ProductStockEntity> stockEntityList = stockMap.getOrDefault(key, new ArrayList<>());
                    stockEntity.setTransferNum(stockEntity.getNum());
                    stockEntityList.add(stockEntity);
                    stockMap.put(key, stockEntityList);
                }
            }
        }
        //成本精度
        ProductFieldPojo costField = saasFormHelp.getProductFieldPojo(RedisPrefixConstant.PRODUCT_COST,ProductEnum.COST.getAttr(), corpid);
        Integer accuracy = costField.getAccuracy();
        Map<String, List<ProductBatchGetVO>> autoBatchMap = new HashMap<>();
        for (String subId : subIds) {
            BatchAutoMatchProductPoJo productPoJo = productMap.get(subId);
            if (Objects.isNull(productPoJo)) {
                continue;
            }
            Double num = productPoJo.getNum();
            String key = productPoJo.getId() + "_" + productPoJo.getWarehouseId();
            boolean enableMultiUnit = Objects.equals(productPoJo.getEnableMultiUnit(), 1);
            List<ProductStockEntity> productStockMap = stockMap.get(key);
            if (Objects.nonNull(productStockMap)) {
                for (ProductStockEntity stockEntity : productStockMap) {
                    if (stockEntity.getTransferNum() <= 0) {
                        continue;
                    }
                    List<ProductBatchGetVO> batchGetVOS = autoBatchMap.getOrDefault(subId, new ArrayList<>());
                    ProductBatchGetVO productBatchGetVO = new ProductBatchGetVO();
                    productBatchGetVO.setId(stockEntity.getId());
                    productBatchGetVO.setParentId(stockEntity.getParentId());
                    productBatchGetVO.setNum(stockEntity.getNum());
                    productBatchGetVO.setBatch(stockEntity.getBatch());
                    productBatchGetVO.setProductNum(stockEntity.getNum());
                    batchGetVOS.add(productBatchGetVO);
                    autoBatchMap.put(subId, batchGetVOS);
                    productBatchGetVO.setProductCost(attrDecimalPrecisionHelper.setPrecision(stockEntity.getCost(),accuracy));
                    Long guaranteePeriod = stockEntity.getGuaranteePeriod();
                    Long produceDate = stockEntity.getProduceDate();
                    if (Objects.nonNull(guaranteePeriod) && !Objects.equals(produceDate, 0L)) {
                        productBatchGetVO.setProduceDate(produceDate);
                        guaranteePeriod = guaranteePeriod / TimeConstant.SECONDS_PER_DAY;
                        productBatchGetVO.setGuaranteePeriod(guaranteePeriod);
                        productBatchGetVO.setExpireDate(produceDate + guaranteePeriod * TimeConstant.SECONDS_PER_DAY);
                    }
                    productBatchGetVO.setCost(stockEntity.getCost());
                    productBatchGetVO.setStock(stockEntity.getNum());
                    productBatchGetVO.setProductNum(stockEntity.getNum());
                    if (enableMultiUnit) {
                        productBatchGetVO.setUnit(productPoJo.getUnit());
                    }
                    if(stockEntity.getTransferNum() >= num){
                        productBatchGetVO.setThisOutStock(num);
                        stockEntity.setTransferNum(Arith.sub(stockEntity.getTransferNum(), num));
                        break;
                    }else {
                        productBatchGetVO.setThisOutStock(stockEntity.getTransferNum());
                        num = Arith.sub(num, stockEntity.getTransferNum());
                        stockEntity.setTransferNum(0D);
                    }
                }
            }
        }
        if (autoBatchMap.isEmpty()) {
            throw new XbbException(ProductErrorCodeEnum.API_ERROR_205079);
        }
        businessProductBatchListVO.setAutoBatchList(autoBatchMap);
        return businessProductBatchListVO;
    }

    @Override
    public PaasFormDataEsListVO guaranteeSearchList(FormDataListDTO formDataListDTO, List<FieldAttrEntity> explainList) throws XbbException {
        PaasFormDataEsListVO formDataListVO = new PaasFormDataEsListVO();
        try {
            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
            BoolQueryBuilder parentBoolQueryBuilder = boolQuery();
            parentBoolQueryBuilder.filter(termQuery("corpid.keyword", formDataListDTO.getCorpid()));
            parentBoolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
            parentBoolQueryBuilder.mustNot(termQuery(ProductEnum.getEsAttr4Keyword(ProductEnum.PARENT_ID), 0));
            parentBoolQueryBuilder.filter(termQuery(ProductEnum.getEsAttr4Keyword(ProductEnum.ENABLE_BATCH_SHELF_LIFE), 1));
            // 产品团队和产品搜索的父查询条件封装
            EsUtil.parseShouldCondition(parentBoolQueryBuilder, formDataListDTO.getShouldConditions(), "", formDataListDTO.getCorpid(), XbbRefTypeEnum.PRODUCT.getCode());
//            List<ConditionsEntityExt> conditionsEntityExtList = new ArrayList<>();

//            EsUtil.parseCondition(parentBoolQueryBuilder, formDataListDTO.getConditions(), "", formDataListDTO.getCorpid(), XbbRefTypeEnum.PRODUCT.getCode());
            // 主表查询
            BoolQueryBuilder boolQueryBuilder = boolQuery();
            boolQueryBuilder.filter(termQuery("corpid.keyword", formDataListDTO.getCorpid()));
            boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
            // 解析查询条件
//            EsUtil.parseCondition(boolQueryBuilder, conditionsEntityExtList, formDataListDTO.getRel(), formDataListDTO.getCorpid(), formDataListDTO.getBusinessType());
            //解析或条件
            EsUtil.parseProductSearchCondition(boolQueryBuilder, formDataListDTO.getProductSerchConditions(), formDataListDTO.getRel(), formDataListDTO.getCorpid(), formDataListDTO.getSubBusinessType());
            HasParentQueryBuilder hasParentQueryBuilder = JoinQueryBuilders.hasParentQuery(IndexTypeEnum.IDX_SAAS_PRODUCT.getType(), parentBoolQueryBuilder, false);
            // 列表页筛选
            List<ConditionsEntityExt> conditions = formDataListDTO.getConditions();
            for (ConditionsEntityExt condition : conditions) {
                if (Objects.equals(ProductEnum.NAME.getAttr(), condition.getAttr())) {
                    parentBoolQueryBuilder.filter(termsQuery(BusinessConstant.ID, condition.getValue()));
                } else if (Objects.equals(ProductEnum.WAREHOUSE.getSaasAttr(), condition.getAttr())) {
                    boolQueryBuilder.filter(termsQuery(ProductStockSubFormEnum.getEsAttr(ProductStockSubFormEnum.WAREHOUSE_ID), condition.getValue()));
                } else if (Objects.equals(SelectProductEnum.BATCH.getSaasAttr(), condition.getAttr())) {
                    boolQueryBuilder.filter(termQuery(ProductStockSubFormEnum.getEsAttr(ProductStockSubFormEnum.BATCH), condition.getValue().get(0)));
                }
            }

            String nameLike = formDataListDTO.getNameLike();
            if (Objects.equals(formDataListDTO.getPlatform(), PlatFormEnum.DINGTALK.getValue()) && !StringUtils.isEmpty(nameLike)) {
                boolQueryBuilder.filter(termQuery(ProductStockSubFormEnum.getEsAttr(ProductStockSubFormEnum.BATCH), nameLike));
            }
            // 除全部分组，其余皆不展示未开启保质期的批次库存
            if (!Objects.equals(formDataListDTO.getListGroupId().intValue(), ListGroupEnum.GUARANTEE_SEARCH.getCode())) {
                boolQueryBuilder.mustNot(termQuery(ProductStockSubFormEnum.getEsAttr(ProductStockSubFormEnum.PRODUCE_DATE), 0));
            }
            EsUtil.parseCondition(boolQueryBuilder, formDataListDTO.getProductSerchConditions(), "", formDataListDTO.getCorpid(), XbbRefTypeEnum.PRODUCT_STOCK_INFO.getCode());
            boolQueryBuilder.filter(hasParentQueryBuilder);
            //设置查询路由
            IndexTypeEnum indexTypeEnum = indexTypeModel.getIndexType(formDataListDTO.getCorpid(), XbbRefTypeEnum.PRODUCT_STOCK_INFO.getCode(), SaasMarkEnum.SAAS.getCode());
            boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, indexTypeEnum.getType()));
            sourceBuilder.query(boolQueryBuilder);
            if (Objects.equals(2, formDataListDTO.getFromExport()) && Objects.nonNull(formDataListDTO.getSearchAfterList()) && formDataListDTO.getSearchAfterList().length>0) {
                // 导出数据的游标
                sourceBuilder.searchAfter(formDataListDTO.getSearchAfterList());
            }
            //排序
            SortOrder order = SortOrder.ASC;
            String sortField = ProductStockSubFormEnum.getEsAttr(ProductStockSubFormEnum.EXPIRE_DATE);
            Map<String, String> sortMap = formDataListDTO.getSortMap();
            if (sortMap != null && !sortMap.isEmpty()) {
                sortField = (StringUtil.isEmpty(sortMap.get("field")) ? sortField : sortMap.get("field"));
                Map<String, FieldAttrEntity> explainMap = formDataListDTO.getExplainMap();
                if (!explainMap.containsKey(sortField)) {
                    String keyword = ".keyword";
                    SelectProductEnum sortFieldEntity = SelectProductEnum.getAttrBySaasAttr(sortField);
                    if (Objects.equals(sortFieldEntity, SelectProductEnum.PRODUCE_DATE)) {
                        sortField = ProductStockSubFormEnum.getEsAttr(ProductStockSubFormEnum.PRODUCE_DATE);
                    } else if (Objects.equals(sortFieldEntity, SelectProductEnum.STOCK)) {
                        sortField = ProductStockSubFormEnum.getEsAttr(ProductStockSubFormEnum.NUM);
                    } else if (Objects.equals(sortFieldEntity, SelectProductEnum.EXPIRE_DATE)) {
                        sortField = ProductStockSubFormEnum.getEsAttr(ProductStockSubFormEnum.EXPIRE_DATE);
                    } else if (Objects.equals(sortFieldEntity, SelectProductEnum.TOTAL_COST)) {
                        sortField = ProductStockSubFormEnum.getEsAttr(ProductStockSubFormEnum.TOTAL_COST);
                    } else if (Objects.equals(sortFieldEntity, SelectProductEnum.BATCH)) {
                        sortField = ProductStockSubFormEnum.getEsAttr(ProductStockSubFormEnum.BATCH);
                    }

                } else {
                    // 排序不存在字段列表中时，给定默认排序，以防报错
                    sortField = ProductStockSubFormEnum.getEsAttr(ProductStockSubFormEnum.EXPIRE_DATE);
                }
                if (SortOrder.ASC.toString().equals(sortMap.get("sort"))) {
                    order = SortOrder.ASC;
                } else {
                    order = SortOrder.DESC;
                }
            }
            sourceBuilder.sort(new FieldSortBuilder(sortField).order(order));
            //限定返回值
            List<String> fieldList = formDataListDTO.getFieldList();
            EsUtil.setFieldList(sourceBuilder, fieldList);
            //分页
            Integer page = formDataListDTO.getPage();
            Integer pageSize = formDataListDTO.getPageSize();
            PageRequest pageRequest = EsUtil.setPage(sourceBuilder, page, pageSize);
            SearchRequest searchRequest = new SearchRequest(indexTypeEnum.getIndex());
            searchRequest.source(sourceBuilder);
            String prefix = "------------------listByEs------------------:";
            long num;
            List<ProductStockEntity> productStockEntities;
            List<PaasFormDataEntity> list;
            Object[] sortValue = new Object[]{};
            if (Objects.equals(formDataListDTO.getFromExport(), 1)) {
                list = xbbElasticsearchRestTemplate.getScrollListForExport(PaasFormDataEntity.class, searchRequest);
                productStockEntities = transferSubFormHelper.transferFormDataToProductStockList(list);
                num = productStockEntities.size();
            } else {
                XbbAggregatedPage<PaasFormDataEntity> esEntities = xbbElasticsearchRestTemplate.queryForPages(pageRequest, searchRequest, PaasFormDataEntity.class);
                if (esEntities == null) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
                }
                list = esEntities.getContent();
                productStockEntities = transferSubFormHelper.transferFormDataToProductStockList(list);
                num = esEntities.getTotalElements();
                sortValue = esEntities.getSortValue();
            }
            List<PaasFormDataEntityExt> resultList = new ArrayList<>();
            Set<Long> productIdSet = new HashSet<>();
            productIdSet.add(-1L);
            for (ProductStockEntity productWarehouseEntity : productStockEntities) {
                productIdSet.add(productWarehouseEntity.getProductId());
            }

            // 产品数据
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
            boolQueryBuilder = boolQuery();
            boolQueryBuilder.filter(termQuery("corpid.keyword", formDataListDTO.getCorpid()));
            boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
            boolQueryBuilder.filter(termsQuery(FieldTypeEnum.DATAID.getAlias(), productIdSet));
            searchSourceBuilder.query(boolQueryBuilder);
            boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, IndexTypeEnum.IDX_SAAS_PRODUCT.getType()));
            List<PaasFormDataEntityExt> paasFormDataEntityExtList = paasEsModel.list(searchSourceBuilder, IndexTypeEnum.IDX_SAAS_PRODUCT, Collections.singletonList(StringConstant.JSON_DATA), BasicConstant.ONE, productIdSet.size());
            Map<Long, PaasFormDataEntityExt> productEntityMap = new HashMap<>();
            paasFormDataEntityExtList.forEach(item -> productEntityMap.put(item.getDataId(), item));

            // 产品成本字段的精度
            FieldAttrEntity productCostField = null;
            FieldAttrEntity costField = null;
            FieldAttrEntity totalCostField = null;
            for (FieldAttrEntity fieldAttrEntity : explainList) {
                if (ProductEnum.COST.getAttr().equals(fieldAttrEntity.getAttr())) {
                    productCostField = fieldAttrEntity;
                } else if (Objects.equals(fieldAttrEntity.getAttr(), SelectProductEnum.COST.getSaasAttr())) {
                    costField = fieldAttrEntity;
                } else if (Objects.equals(fieldAttrEntity.getAttr(), SelectProductEnum.TOTAL_COST.getSaasAttr())) {
                    totalCostField = fieldAttrEntity;
                }
            }

            explainList.removeIf(item -> (Objects.equals(item.getAttr(), ProductEnum.WAREHOUSE.getAttr()) || Objects.equals(item.getAttr(), ProductEnum.STOCK.getAttr()) || Objects.equals(item.getAttr(), ProductEnum.COST.getAttr())));
            for (ProductStockEntity productStockEntity : productStockEntities) {
                if (productEntityMap.containsKey(productStockEntity.getProductId())) {
                    PaasFormDataEntityExt paasFormDataEntityExt = (PaasFormDataEntityExt) CloneUtil.deepClone(productEntityMap.get(productStockEntity.getProductId()));
                    JSONObject extData = paasFormDataEntityExt.getData();
                    // 生产日期
                    extData.put(SelectProductEnum.PRODUCE_DATE.getSaasAttr(), productStockEntity.getProduceDate());
                    // 到期时间
                    extData.put(SelectProductEnum.EXPIRE_DATE.getSaasAttr(), productStockEntity.getProduceDate() + productStockEntity.getGuaranteePeriod());
                    // 批次号
                    extData.put(SelectProductEnum.BATCH.getSaasAttr(), productStockEntity.getBatch());
                    // 仓库
                    extData.put(SelectProductEnum.WAREHOUSE.getSaasAttr(), productStockEntity.getWarehouseName());
                    // 保质期
                    if (!Objects.equals(productStockEntity.getProduceDate(), 0L) && Objects.nonNull(productStockEntity.getProduceDate())) {
                        extData.put(SelectProductEnum.GUARANTEE_PERIOD.getSaasAttr(), productStockEntity.getGuaranteePeriod() / 86400);
                    }
                    // 库存数量
                    extData.put(SelectProductEnum.STOCK.getSaasAttr(), productStockEntity.getNum());
                    Double cost = productStockEntity.getCost();
                    if (productStockEntity.getNum() == 0D) {
                        cost = 0D;
                        // 成本
                        extData.put(SelectProductEnum.COST.getSaasAttr(), BasicConstant.NULL_SHOW_STR);
                        // 成本小计
                        if (Objects.nonNull(productStockEntity.getCost()) && Objects.nonNull(productStockEntity.getNum())) {
                            extData.put(SelectProductEnum.TOTAL_COST.getSaasAttr(), BasicConstant.NULL_SHOW_STR);
                        }
                    } else if (Objects.nonNull(productCostField) && BasicConstant.ONE.equals(productCostField.getAmountFlag())) {
                        // 成本
                        extData.put(SelectProductEnum.COST.getSaasAttr(),parseThousandth(cost, productCostField.getAccuracy()));
                        // 成本小计
                        if (Objects.nonNull(productStockEntity.getCost()) && Objects.nonNull(productStockEntity.getNum())) {
                            extData.put(SelectProductEnum.TOTAL_COST.getSaasAttr(), parseThousandth(Arith.mul(productStockEntity.getNum(), cost), productCostField.getAccuracy()));
                        }
                    } else {
                        // 成本
                        extData.put(SelectProductEnum.COST.getSaasAttr(), cost);
                        // 成本小计
                        if (Objects.nonNull(productStockEntity.getCost()) && Objects.nonNull(productStockEntity.getNum())) {
                            extData.put(SelectProductEnum.TOTAL_COST.getSaasAttr(), Arith.mul(productStockEntity.getNum(), cost));
                        }
                    }
                    // 剩余天数
                    if (!Objects.equals(productStockEntity.getProduceDate(), 0L)) {
                        Long expireDays = (productStockEntity.getProduceDate() + productStockEntity.getGuaranteePeriod() - DateTimeUtil.getTodayInt()) / 86400;
                        extData.put(ListOptionEnum.GUARANTEE_SEARCH.getAttr(), expireDays);
                        if (expireDays.compareTo(0L) >= 0) {
                            extData.put("redFlag", BasicConstant.ZERO);
                        } else {
                            extData.put("redFlag", BasicConstant.ONE);
                        }
                    }
                    paasFormDataEntityExt.setTagData(new JSONObject());
                    resultList.add(paasFormDataEntityExt);
                }
            }
            PageHelper pageHelper = new PageHelper(page, pageSize);
            pageHelper.setRowsCount((int) num);
            formDataListVO.setPaasFormDataESList(resultList);
            formDataListVO.setPageHelper(pageHelper);
            formDataListVO.setBusinessType(formDataListDTO.getBusinessType());
            formDataListVO.setSortValue(sortValue);
        } catch (Exception e) {
            LOG.error("es查询出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return formDataListVO;
    }

    /**
     * 金额千份位解析
     * @param value
     * @return
     */
    public Object parseThousandth(Object value, Integer accuracy){
        if(Objects.isNull(value)){
            return value;
        }
        if (accuracy == null) {
            accuracy = BasicConstant.DEFAULT_ACCURACY;
        }
        String pattern = "##,##0.";
        if (Objects.equals(accuracy, 0)) {
            pattern = "##,##0";
        }
        for (int i = 0; i < accuracy; i++) {
            pattern = pattern + "0";
        }
        DecimalFormat df = new DecimalFormat(pattern);
        if(value instanceof Integer || value instanceof Double ||
                value instanceof BigDecimal || value instanceof Long || StringUtil.isDigital(value.toString())){
            return df.format(Double.parseDouble(String.valueOf(value)));
        }
        return value;
    }
}
